package team.pwy.service;

import co.elastic.clients.elasticsearch.ElasticsearchClient;

import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.data.elasticsearch.core.query.HighlightQuery;
import org.springframework.data.elasticsearch.core.query.highlight.Highlight;
import org.springframework.data.elasticsearch.core.query.highlight.HighlightField;
import org.springframework.data.elasticsearch.core.query.highlight.HighlightParameters;
import org.springframework.stereotype.Service;
import team.pwy.pojo.entity.Movie;
import team.pwy.pojo.entity.MovieIndex;
import team.pwy.pojo.entity.TypeIndex;
import team.pwy.vo.TypeVo;

import java.io.IOException;
import java.util.*;

@Service
public class MovieIndexServiceImpl implements MovieIndexService {

    private static final Logger log = LoggerFactory.getLogger(MovieIndexServiceImpl.class);

    @Resource
    private MovieService movieService;

    @Resource
    private ElasticsearchTemplate elasticsearchTemplate;

    @Resource
    MovieIndexRepository contentsRepository;//

    @Resource
    ElasticsearchClient elasticsearchClient;//

    @Resource
    private TypeIndexRepository typeIndexRepository;//

    @Resource
    ElasticsearchOperations operations;

    /**
     * 初始化索引结构和数据
     */
    public void initIndex() {

        // 处理索引结构
        IndexOperations indexOps = elasticsearchTemplate.indexOps(MovieIndex.class);
        System.out.println(indexOps.exists());
        if (indexOps.exists()) {
            boolean delFlag = indexOps.delete();
            log.info("movie_index exists，delete:{}", delFlag);
//            indexOps.createMapping(ContentsIndex.class);
            indexOps.createWithMapping();
        } else {
            log.info("movie_index not exists");
            indexOps.createWithMapping();
        }
        // 同步数据库表记录
        List<Movie> moviesList = movieService.findAll();
        if (!moviesList.isEmpty()) {
            List<MovieIndex> contentsIndexList = new ArrayList<>();
            moviesList.forEach(contents -> {
                MovieIndex contentsIndex = new MovieIndex();
                BeanUtils.copyProperties(contents, contentsIndex);
                contentsIndexList.add(contentsIndex);
            });
            contentsIndexList.forEach(System.out::println);
            elasticsearchTemplate.save(contentsIndexList);
        }
    }

    @Override
    public SearchHits<MovieIndex> findMovieIndexByCountryAndStatus(TypeVo typeVo, Integer pageNum, Integer pageSize) throws IOException {

        String type = typeVo.getType();
        String country = typeVo.getCountry();
        String search = typeVo.getSearch();

        List<String> movieIdList = new ArrayList<>();

        if (type != null && !type.isEmpty()) {
            // 多表查询
            Criteria criteriaType = new Criteria(typeVo.getType()).is(1);
            CriteriaQuery query = new CriteriaQuery(criteriaType);
            SearchHits<TypeIndex> hits = operations.search(query, TypeIndex.class);
            for (SearchHit<TypeIndex> hit : hits) {
                TypeIndex typeIndex = hit.getContent();
                movieIdList.add(String.valueOf(typeIndex.getId()));
            }
        } else {
            Iterable<TypeIndex> all = typeIndexRepository.findAll();
            for (TypeIndex hit : all) {
                movieIdList.add(hit.getMoveId().toString());
            }
        }

        SearchHits<MovieIndex> movieHits = null;
        // 页面刷新
        if ((country == null || country.isEmpty()) && (search == null || search.isEmpty())) {
            Criteria criteriaMovie = new Criteria("id").in(movieIdList)
                    .and("status").is(typeVo.getStatus())
                    .and("firstDate")
                    .between(typeVo.getFirstDate(), typeVo.getEndDate());
            CriteriaQuery queryMovie = new CriteriaQuery(criteriaMovie).setPageable(PageRequest.of((pageNum - 1) , pageSize))
                    .addSort(Sort.by(Sort.Direction.DESC, typeVo.getOrder()));
            movieHits = operations.search(queryMovie, MovieIndex.class);

        } else if ((country != null && !country.isEmpty()) && (search == null || search.isEmpty())) {
            Criteria criteriaMovie = new Criteria("id").in(movieIdList)
                    .and("status").is(typeVo.getStatus())
                    .and("country").is(country)
                    .and("firstDate").between(typeVo.getFirstDate(), typeVo.getEndDate());
            CriteriaQuery queryMovie = new CriteriaQuery(criteriaMovie).setPageable(PageRequest.of((pageNum - 1) , pageSize))
                    .addSort(Sort.by(Sort.Direction.DESC, typeVo.getOrder()));
            movieHits = operations.search(queryMovie, MovieIndex.class);

        } else if (country == null || country.isEmpty()) {

            HighlightParameters parameters  = new HighlightParameters.HighlightParametersBuilder().withPreTags("<span style='color:red'>").withPostTags("</span>").withNumberOfFragments(0).build();

            List<HighlightField> fields = new ArrayList<>();
            HighlightField title = new HighlightField("title");
            fields.add(title);

            HighlightQuery highlightQuery = new HighlightQuery(new Highlight(parameters,fields), MovieIndex.class);

            Criteria criteriaMovie = new Criteria("id").in(movieIdList)
                    .and("status").is(typeVo.getStatus())
                    .and("title").matches(search)
                    .and("firstDate").between(typeVo.getFirstDate(), typeVo.getEndDate());
            CriteriaQuery queryMovie = new CriteriaQuery(criteriaMovie).setPageable(PageRequest.of((pageNum - 1) , pageSize))
                    .addSort(Sort.by(Sort.Direction.DESC, typeVo.getOrder()));

            queryMovie.setHighlightQuery(highlightQuery);
            movieHits = operations.search(queryMovie, MovieIndex.class);

        } else {
            HighlightParameters parameters  = new HighlightParameters.HighlightParametersBuilder().withPreTags("<span style='color:red'>").withPostTags("</span>").withNumberOfFragments(0).build();

            List<HighlightField> fields = new ArrayList<>();
            HighlightField title = new HighlightField("title");
            fields.add(title);

            HighlightQuery highlightQuery = new HighlightQuery(new Highlight(parameters,fields), MovieIndex.class);

            Criteria criteriaMovie = new Criteria("id").in(movieIdList)
                    .and("status").is(typeVo.getStatus())
                    .and("title").matches(search)
                    .and("country").is(country)
                    .and("firstDate")
                    .between(typeVo.getFirstDate(), typeVo.getEndDate());
            CriteriaQuery queryMovie = new CriteriaQuery(criteriaMovie).setPageable(PageRequest.of((pageNum - 1) , pageSize))
                    .addSort(Sort.by(Sort.Direction.DESC, typeVo.getOrder()));

            queryMovie.setHighlightQuery(highlightQuery);
            movieHits = operations.search(queryMovie, MovieIndex.class);

        }
        return movieHits;
    }
}